home *** CD-ROM | disk | FTP | other *** search
- /*
- $Id$
- $Log$
- Desc:
- Lang: english
- */
- #include "exec_intern.h"
- #include "semaphores.h"
-
- /*****************************************************************************
-
- NAME */
- #include <exec/semaphores.h>
- #include <clib/exec_protos.h>
-
- __AROS_LH1(void, ReleaseSemaphore,
-
- /* SYNOPSIS */
- __AROS_LA(struct SignalSemaphore *, sigSem, A0),
-
- /* LOCATION */
- struct ExecBase *, SysBase, 95, Exec)
-
- /* FUNCTION
- Releases a lock on a semaphore obtained with either ObtainSemaphore(),
- ObtainSemaphoreShared(), AttemptSemaphore or AttemptSemaphoreShared().
- Each call to one of those functions must be accompanied with one
- call to ReleasSemaphore().
-
- INPUTS
- sigSem - pointer to semaphore structure
-
- RESULT
-
- NOTES
- This function preserves all registers.
-
- EXAMPLE
-
- BUGS
-
- SEE ALSO
-
- INTERNALS
-
- HISTORY
- 29-10-95 digulla automatically created from
- exec_lib.fd and clib/exec_protos.h
- 22-01-96 fleischer implementation
-
- *****************************************************************************/
- {
- __AROS_FUNC_INIT
- __AROS_BASE_EXT_DECL(struct ExecBase *,SysBase)
-
- /* Arbitrate for the semaphore structure */
- Forbid();
-
- /* Lower the use count. >0 means exclusive, <0 shared locked */
- if(sigSem->ss_NestCount>0)
- sigSem->ss_NestCount--;
- else
- sigSem->ss_NestCount++;
-
- /*
- Now if the semaphore is free and there are other tasks waiting
- wake them up.
- */
- if(!sigSem->ss_NestCount&&sigSem->ss_WaitQueue.mlh_Head->mln_Succ!=NULL)
- {
- /* Get first node in the waiting list */
- struct SemaphoreNode *sn;
- sn=(struct SemaphoreNode *)sigSem->ss_WaitQueue.mlh_Head;
-
- /* Is it a shared lock? */
- if((ULONG)sn->node.ln_Name!=SM_EXCLUSIVE)
- {
- /* Yes. Process all shared locks in the list. */
- while(sn->node.ln_Succ!=NULL)
- {
- /* Remember node */
- struct SemaphoreNode *on=sn;
-
- /* Get next node now because there is a Remove() lurking */
- sn=(struct SemaphoreNode *)sn->node.ln_Succ;
-
- /* Is this a shared lock? */
- if((ULONG)on->node.ln_Name!=SM_EXCLUSIVE)
- {
- /* Yes. Remove it from the list */
- Remove(&on->node);
-
- /* Wake the new owner. Check access type. */
- if(on->node.ln_Pri==SN_TYPE_OBTAIN)
- /* ObtainSemaphore() type. Send the semaphore signal. */
- Signal(on->task,SEMAPHORESIGF);
- else
- {
- /* Procure() type. Reply the semaphore message. */
- ((struct SemaphoreMessage *)on)->ssm_Semaphore=sigSem;
- ReplyMsg((struct Message *)on);
- }
-
- /*
- Mark the semaphore as having one more openers.
- This happens here because the new owner(s) may need
- some time to really wake up and I don't want other
- tasks obtaining the semaphore before him.
- */
- sigSem->ss_NestCount--;
- }
- /* Dito. Invalidate the owner field. */
- sigSem->ss_Owner=NULL;
- }
- }else
- {
- /* The new owner wants an exclusive lock. Remove him from the list. */
- Remove(&sn->node);
-
- /* Check access type */
- if(sn->node.ln_Pri==SN_TYPE_OBTAIN)
- {
- /*
- ObtainSemaphore() type. Set the owner field and
- Send the semaphore signal.
- */
- sigSem->ss_Owner=sn->task;
- Signal(sn->task,SEMAPHORESIGF);
- }else
- {
- /* Procure() type. Reply the message. */
- ((struct SemaphoreMessage *)sn)->ssm_Semaphore=sigSem;
- sigSem->ss_Owner=((struct Message *)sn)->mn_ReplyPort->mp_SigTask;
- ReplyMsg((struct Message *)sn);
- }
- /* Mark the semaphore as having one more openers. */
- sigSem->ss_NestCount++;
- }
- }
-
- /* All done. */
- Permit();
- __AROS_FUNC_EXIT
- } /* ReleaseSemaphore */
-